import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from app.songlib.song_library_manager import SongLibraryManager
from app.utils import get_file_info, play_audio_file


class SongLibraryView:
    """歌曲库视图类，负责歌曲库UI的创建和管理"""
    
    def __init__(self, parent_frame):
        """初始化歌曲库视图"""
        self.parent_frame = parent_frame
        self.root = None  # 将在设置主窗口时设置
        
        # 创建歌曲库管理器
        self.library_manager = SongLibraryManager()
        
        # 初始化文件夹路径映射字典
        self.folder_path_map = {}
        
        # 创建界面组件
        self.create_widgets()
        
        # 初始加载文件夹和歌曲
        self.refresh_library()
    
    def set_root(self, root):
        """设置主窗口引用"""
        self.root = root
    
    def create_widgets(self):
        """创建歌曲库视图的所有UI组件"""
        # 清除占位符
        for widget in self.parent_frame.winfo_children():
            widget.destroy()
        
        # 创建歌曲库主框架
        self.main_frame = ttk.Frame(self.parent_frame, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建左侧目录区域
        self.left_frame = ttk.LabelFrame(self.main_frame, text="音乐文件夹", padding="5", width=260)
        self.left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=5, pady=5)
        self.left_frame.pack_propagate(0)  # 防止框架随内容缩放
        
        # 创建文件夹管理按钮
        button_frame = ttk.Frame(self.left_frame, padding="5")
        button_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.add_folder_btn = ttk.Button(button_frame, text="添加文件夹", command=self.add_library_folder)
        self.add_folder_btn.pack(side=tk.LEFT, padx=2)
        
        self.remove_folder_btn = ttk.Button(button_frame, text="删除文件夹", command=self.remove_library_folder)
        self.remove_folder_btn.pack(side=tk.LEFT, padx=2)
        
        self.refresh_btn = ttk.Button(button_frame, text="刷新", command=self.refresh_library)
        self.refresh_btn.pack(side=tk.LEFT, padx=2)
        
        # 创建文件夹列表区域
        folder_list_frame = ttk.Frame(self.left_frame, padding="5")
        folder_list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建带有滚动条的画布来容纳文件夹列表
        self.folder_canvas = tk.Canvas(folder_list_frame)
        self.folder_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 创建滚动条
        folder_scrollbar = ttk.Scrollbar(folder_list_frame, orient="vertical", command=self.folder_canvas.yview)
        folder_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.folder_canvas.config(yscrollcommand=folder_scrollbar.set)
        
        # 创建框架来容纳所有文件夹项
        self.folder_items_frame = ttk.Frame(self.folder_canvas)
        self.folder_canvas_frame = self.folder_canvas.create_window((0, 0), window=self.folder_items_frame, anchor="nw")
        
        # 绑定滚动事件
        self.folder_canvas.bind("<Configure>", self._on_canvas_configure)
        self.folder_items_frame.bind("<Configure>", self._on_frame_configure)
        self.folder_canvas.bind("<MouseWheel>", self._on_mousewheel)
        self.folder_items_frame.bind("<MouseWheel>", lambda e: "break")
        
        # 创建中间歌曲列表区域
        self.middle_frame = ttk.LabelFrame(self.main_frame, text="音频文件", padding="5")
        self.middle_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建搜索框
        search_frame = ttk.Frame(self.middle_frame, padding="5")
        search_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(search_frame, text="搜索: ").pack(side=tk.LEFT, padx=2)
        self.search_var = tk.StringVar()
        self.search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=50)
        self.search_entry.pack(side=tk.LEFT, padx=2, fill=tk.X, expand=True)
        self.search_entry.bind("<KeyRelease>", self.search_songs)
        
        # 创建歌曲列表区域
        song_list_frame = ttk.Frame(self.middle_frame, padding="5")
        song_list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建歌曲列表树视图
        columns = ("filename", "path")
        self.song_tree = ttk.Treeview(song_list_frame, columns=columns, show="headings", height=15)
        
        # 配置列
        self.song_tree.heading("filename", text="文件名")
        self.song_tree.heading("path", text="文件路径")
        self.song_tree.column("filename", width=200, anchor=tk.W)
        self.song_tree.column("path", width=400, anchor=tk.W)
        
        # 绑定点击事件
        self.song_tree.bind("<<TreeviewSelect>>", self.on_song_select)
        # 绑定双击事件，用于播放音频文件
        self.song_tree.bind("<Double-1>", self.on_song_double_click)
        
        # 添加滚动条
        song_scrollbar = ttk.Scrollbar(song_list_frame, orient="vertical", command=self.song_tree.yview)
        self.song_tree.configure(yscrollcommand=song_scrollbar.set)
        
        # 放置树视图和滚动条
        self.song_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        song_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建右侧详细信息区域
        self.right_frame = ttk.LabelFrame(self.main_frame, text="歌曲详情", padding="5")
        self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=5, pady=5, ipady=5)
        
        # 创建详情信息标签
        self.details_text = tk.Text(self.right_frame, width=40, height=15, wrap=tk.WORD, state=tk.DISABLED)
        self.details_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    
    def _on_canvas_configure(self, event):
        """当画布大小改变时调整画布"""
        self.folder_canvas.itemconfig(self.folder_canvas_frame, width=event.width)
    
    def _on_frame_configure(self, event):
        """当框架大小改变时更新滚动区域，只有当内容高度超过画布高度时才启用滚动"""
        canvas_height = self.folder_canvas.winfo_height()
        frame_height = self.folder_items_frame.winfo_height()
        
        # 只有当框架高度大于画布高度时才允许滚动
        if frame_height > canvas_height:
            self.folder_canvas.configure(scrollregion=self.folder_canvas.bbox("all"))
        else:
            # 否则设置滚动区域为空，不允许滚动
            self.folder_canvas.configure(scrollregion="")
    
    def _on_mousewheel(self, event):
        """处理鼠标滚轮事件，只有当内容超出画布时才响应滚动"""
        canvas_height = self.folder_canvas.winfo_height()
        frame_height = self.folder_items_frame.winfo_height()
        
        # 只有当框架高度大于画布高度时才允许滚动
        if frame_height > canvas_height:
            self.folder_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
    
    def refresh_library(self):
        """刷新歌曲库显示"""
        # 清除文件夹列表
        for widget in self.folder_items_frame.winfo_children():
            widget.destroy()
        
        # 创建或清空映射字典
        self.folder_path_map = {}
        
        # 重新加载文件夹
        for folder_path in self.library_manager.library_folders:
            # 添加文件夹到列表，并标记选中状态
            folder_name = os.path.basename(folder_path) if folder_path else "未命名文件夹"
            is_selected = folder_path in self.library_manager.selected_folders
            
            # 创建文件夹项框架
            folder_frame = ttk.Frame(self.folder_items_frame)
            folder_frame.pack(fill=tk.X, padx=2, pady=1)
            
            # 创建复选框
            var = tk.BooleanVar(value=is_selected)
            checkbox = ttk.Checkbutton(folder_frame, variable=var, text="")
            checkbox.pack(side=tk.LEFT, padx=2)
            
            # 创建文件夹名称标签
            label = ttk.Label(folder_frame, text=folder_name, anchor=tk.W, width=30)
            label.pack(side=tk.LEFT, padx=2, fill=tk.X, expand=True)
            
            # 存储实际路径信息
            folder_id = f"folder_{len(self.folder_path_map)}"
            self.folder_path_map[folder_id] = folder_path
            
            # 绑定点击事件到框架
            folder_frame.bind("<Button-1>", lambda event, fid=folder_id, v=var: self.on_folder_check(event, fid, v))
            checkbox.bind("<Button-1>", lambda event, fid=folder_id, v=var: self.on_folder_check(event, fid, v))
            label.bind("<Button-1>", lambda event, fid=folder_id, v=var: self.on_folder_check(event, fid, v))
        
        # 刷新歌曲列表
        self.refresh_song_list()
    
    def refresh_song_list(self):
        """刷新歌曲列表"""
        # 清除歌曲列表
        for item in self.song_tree.get_children():
            self.song_tree.delete(item)
        
        # 获取所有歌曲
        all_songs = self.library_manager.get_all_songs()
        
        # 应用搜索过滤
        search_text = self.search_var.get().lower()
        if search_text:
            filtered_songs = [song for song in all_songs if search_text in song['filename'].lower() or search_text in song['path'].lower()]
        else:
            filtered_songs = all_songs
        
        # 添加歌曲到列表
        for song in filtered_songs:
            # 获取目录路径（不包含文件名）
            folder_path = os.path.dirname(song['path'])
            # 统一路径中的斜杠为正斜杠
            folder_path = folder_path.replace('\\', '/')
            self.song_tree.insert("", tk.END, values=(song['filename'], folder_path))
    
    def add_library_folder(self):
        """添加歌曲库文件夹"""
        folder_path = filedialog.askdirectory(title="选择音乐文件夹")
        if folder_path:
            success = self.library_manager.add_library_folder(folder_path)
            if success:
                self.refresh_library()
            else:
                messagebox.showerror("错误", "添加文件夹失败或文件夹已存在")
    
    def remove_library_folder(self):
        """删除歌曲库文件夹"""
        # 创建临时存储选中文件夹的列表
        selected_folders = []
        
        # 遍历所有文件夹项
        for widget in self.folder_items_frame.winfo_children():
            if isinstance(widget, ttk.Frame):
                # 查找复选框和标签
                for child in widget.winfo_children():
                    if isinstance(child, ttk.Checkbutton) and child.instate(['selected']):
                        # 获取文件夹名称
                        folder_name = ""
                        for sub_child in widget.winfo_children():
                            if isinstance(sub_child, ttk.Label):
                                folder_name = sub_child.cget("text")
                                break
                        
                        # 根据文件夹名称查找对应的路径
                        for folder_id, folder_path in self.folder_path_map.items():
                            if os.path.basename(folder_path) == folder_name or folder_name == "未命名文件夹" and folder_path in self.library_manager.library_folders:
                                selected_folders.append(folder_path)
                                break
                        break
        
        if not selected_folders:
            messagebox.showinfo("提示", "请先选择要删除的文件夹")
            return
        
        # 只处理第一个选中的文件夹（为简化逻辑）
        folder_path = selected_folders[0]
        
        # 确认删除
        if messagebox.askyesno("确认", f"确定要删除文件夹 '{os.path.basename(folder_path)}' 吗？"):
            success = self.library_manager.remove_library_folder(folder_path)
            if success:
                self.refresh_library()
            else:
                messagebox.showerror("错误", "删除文件夹失败")
    
    def on_folder_check(self, event, folder_id, var):
        """处理文件夹复选框点击事件"""
        # 获取文件夹路径
        folder_path = self.folder_path_map.get(folder_id)

        if folder_path:
            # 获取复选框的当前状态
            current_state = var.get()
            
            # 计算新状态（与当前状态相反）
            new_state = not current_state
            
            # 更新复选框状态
            var.set(new_state)
            
            # 更新文件夹的选中状态
            self.library_manager.toggle_folder_selection(folder_path, new_state)
            
            # 刷新歌曲列表
            self.refresh_song_list()
        
        # 在Tkinter中，返回"break"可以阻止事件冒泡
        return "break"
    
    def on_song_select(self, event):
        """处理歌曲选择事件，显示歌曲详细信息"""
        selected_items = self.song_tree.selection()
        if not selected_items:
            return
        
        # 获取选中的歌曲信息
        item = selected_items[0]
        filename = self.song_tree.item(item, "values")[0]
        folder_path = self.song_tree.item(item, "values")[1]
        
        # 构建完整的歌曲路径
        song_path = os.path.join(folder_path, filename)
        # 确保路径分隔符正确
        song_path = song_path.replace('/', os.path.sep)
        
        # 获取歌曲详细信息
        song_details = self.library_manager.get_song_details(song_path)
        
        # 更新详情文本
        self.details_text.config(state=tk.NORMAL)
        self.details_text.delete(1.0, tk.END)
        
        if song_details:
            details_str = """
文件信息:
-----------
文件名: {}
文件大小: {}
文件格式: {}
文件路径: {}
修改时间: {}
            """
            # 将路径中的反斜杠替换为正斜杠
            formatted_path = song_details['path'].replace('\\', '/')
            self.details_text.insert(tk.END, details_str.format(
                song_details['filename'],
                song_details['size'],
                song_details['format'],
                formatted_path,
                song_details['modified_time']
            ))
        else:
            self.details_text.insert(tk.END, "无法获取歌曲详细信息")
        
        self.details_text.config(state=tk.DISABLED)
    
    def search_songs(self, event=None):
        """搜索歌曲"""
        self.refresh_song_list()
        
    def on_song_double_click(self, event):
        """处理歌曲双击事件，使用默认播放器播放音频文件"""
        selected_items = self.song_tree.selection()
        if not selected_items:
            return
        
        # 获取选中的歌曲信息
        item = selected_items[0]
        filename = self.song_tree.item(item, "values")[0]
        folder_path = self.song_tree.item(item, "values")[1]
        
        # 构建完整的歌曲路径
        song_path = os.path.join(folder_path, filename)
        # 确保路径分隔符正确
        song_path = song_path.replace('/', os.path.sep)
        
        # 使用默认播放器播放音频文件
        play_audio_file(song_path)